home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume7 / regex < prev    next >
Encoding:
Text File  |  1988-10-17  |  35.4 KB  |  1,522 lines

  1. Reply-To: oz@yetti.UUCP (Ozan Yigit)
  2. Subject:  v07i021:  Ed(1)/regex(3)-compatible reg. exp. package
  3. Newsgroups: mod.sources
  4. Approved: mirror!rs
  5.  
  6. Submitted by: ihnp4!yetti!oz (Ozan Yigit)
  7. Mod.sources: Volume 7, Issue 21
  8. Archive-name: regex
  9.  
  10. #!/bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #!/bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create the files:
  15. #    README.txt
  16. #    regex.3
  17. #    regex.c
  18. #    re_fail.c
  19. #    grep.c
  20. #    makefile
  21. # This archive created: Thu Aug 14 17:41:27 1986
  22. export PATH; PATH=/bin:$PATH
  23. echo shar: extracting "'README.txt'" '(1925 characters)'
  24. if test -f 'README.txt'
  25. then
  26.     echo shar: over-writing existing file "'README.txt'"
  27. fi
  28. sed 's/^X//' << \SHAR_EOF > 'README.txt'
  29. XThis is a pre-release of a bunch of berkelix regex(3)/ed(1)
  30. Xcompatible regular-expression routines.
  31. X
  32. XThese routines are completely public domain. You can do whatever
  33. Xyou like with them, and hopefully you are professional enough not
  34. Xto strip out the authorship information, acknowledgements and
  35. Xreferences.
  36. X
  37. XThe reason for this being a *pre-release* is that I received a lot
  38. Xof useful suggestions about packaging, about additional routines etc.
  39. Xfrom a few people. I do not have too much time to do those changes
  40. Xright now, so I am putting this package out for those who needed
  41. Xit yesterday. Next release will include other routines, and better
  42. Xpackaging.
  43. X
  44. XThese routines are *not* tested under SysV, but they are tested
  45. Xunder PRO/Venix (2.0) and BSD 4.2.
  46. X
  47. XThose uEmacs V30 hackers should take notice of this package,
  48. Xas well as those who would love to replace the "restricted" regex
  49. Xroutines in Jove. [Since parts of these routines are based on Conroy's
  50. Xoriginal work, it would be only fitting to put these into uEmacs.]
  51. X
  52. XIn general, these routines run just as fast, or faster than regex library
  53. Xroutines under BSD 4.2. In some cases, they are slightly slower. I did not
  54. Xtry too hard to optimize the re_exec routine.
  55. X
  56. XCoding style is a la K&R, with lotsa short identifiers. I like it
  57. Xthat way. All flames should be fed to yetti!dragon.
  58. X
  59. XAcknowledgements: Henry Spencer, Hugh Redelmeier and Drew Sullivan made
  60. X          a lot of important suggestions, some of which will be
  61. X          incorporated into the next version.
  62. X
  63. X
  64. XPackage:
  65. X    ----------------------------------------------------
  66. X    README.txt        this file.
  67. X
  68. X    regex.3            comprehensive man page
  69. X    regex.c            goodies
  70. X
  71. X    re_fail.c        sample failure routine
  72. X
  73. X    grep.c            a tiny grep for timing tests
  74. X
  75. X    makefile        guess.
  76. X    ----------------------------------------------------
  77. X
  78. Xenjoy..          oz    [...!utzoo!yetti!oz]
  79. X            [oz@yusol.BITNET || oz@yuyetti.BITNET]
  80. X
  81. X            Dept. of Computer Science
  82. X            York University
  83. SHAR_EOF
  84. if test 1925 -ne "`wc -c 'README.txt'`"
  85. then
  86.     echo shar: error transmitting "'README.txt'" '(should have been 1925 characters)'
  87. fi
  88. echo shar: extracting "'regex.3'" '(7847 characters)'
  89. if test -f 'regex.3'
  90. then
  91.     echo shar: over-writing existing file "'regex.3'"
  92. fi
  93. sed 's/^X//' << \SHAR_EOF > 'regex.3'
  94. X.TH regex 3 local
  95. X.DA Jun 19 1986
  96. X.SH NAME
  97. Xre_comp, re_exec, re_subs, re_modw, re_fail  \- regular expression handling
  98. X.SH ORIGIN
  99. XDept. of Computer Science
  100. X.br
  101. XYork University
  102. X.SH SYNOPSIS
  103. X.B char *re_comp(pat)
  104. X.br
  105. X.B char *pat;
  106. X.PP
  107. X.B re_exec(str)
  108. X.br
  109. X.B char *str;
  110. X.PP
  111. X.B re_subs(src, dst)
  112. X.br
  113. X.B char *src;
  114. X.br
  115. X.B char *dst;
  116. X.PP
  117. X.B void re_fail(msg, op)
  118. X.br
  119. X.B char *msg;
  120. X.br
  121. X.B char op;
  122. X.PP
  123. X.B void re_modw(str)
  124. X.br
  125. X.B char *str;
  126. X
  127. X.SH DESCRIPTION
  128. X.PP
  129. XThese functions implement
  130. X.IR ed (1)-style
  131. Xpartial regular expressions and supporting facilities.
  132. X.PP
  133. X.I Re_comp
  134. Xcompiles a pattern string into an internal form (a deterministic finite-state
  135. Xautomaton) to be executed by
  136. X.I re_exec
  137. Xfor pattern matching.
  138. X.I Re_comp
  139. Xreturns 0 if the pattern is compiled successfully, otherwise it returns an
  140. Xerror message string. If
  141. X.I re_comp
  142. Xis called with a 0 or a \fInull\fR string, it returns without changing the
  143. Xcurrently compiled regular expression.
  144. X.sp
  145. X.I Re_comp
  146. Xsupports the same limited set of
  147. X.I regular expressions
  148. Xfound in
  149. X.I ed
  150. Xand Berkeley
  151. X.IR regex (3)
  152. Xroutines:
  153. X.sp
  154. X.if n .in +1.6i
  155. X.if t .in +1i
  156. X.de Ti
  157. X.if n .ti -1.6i
  158. X.if t .ti -1i
  159. X.. 
  160. X.if n .ta 0.8i +0.8i +0.8i
  161. X.if t .ta 0.5i +0.5i +0.5i
  162. X.Ti 
  163. X[1]    \fIchar\fR    Matches itself, unless it is a special
  164. Xcharacter (meta-character): \fB. \\ [ ] * + ^ $\fR
  165. X
  166. X.Ti 
  167. X[2]    \fB.\fR    Matches \fIany\fR character.
  168. X
  169. X.Ti 
  170. X[3]    \fB\\\fR    Matches the character following it, except
  171. Xwhen followed by a digit 1 to 9, \fB(\fR, fB)\fR, \fB<\fR or \fB>\fR.
  172. X(see [7], [8] and [9]) It is used as an escape character for all 
  173. Xother meta-characters, and itself. When used
  174. Xin a set ([4]), it is treated as an ordinary
  175. Xcharacter.
  176. X
  177. X.Ti
  178. X[4]    \fB[\fIset\fB]\fR    Matches one of the characters in the set.
  179. XIf the first character in the set is \fB^\fR,
  180. Xit matches a character NOT in the set. A
  181. Xshorthand 
  182. X.IR S - E
  183. Xis used to specify a set of
  184. Xcharacters 
  185. X.I S 
  186. Xup to 
  187. X.IR E , 
  188. Xinclusive. The special
  189. Xcharacters \fB]\fR and \fB-\fR have no special
  190. Xmeaning if they appear as the first chars
  191. Xin the set.
  192. X.nf
  193. X    examples:    match:
  194. X    [a-z]        any lowercase alpha
  195. X    [^]-]        any char except ] and -
  196. X    [^A-Z]        any char except 
  197. X            uppercase alpha
  198. X    [a-zA-Z0-9]    any alphanumeric
  199. X.fi
  200. X
  201. X.Ti 
  202. X[5]    \fB*\fR    Any regular expression form [1] to [4], followed by
  203. Xclosure char (*) matches zero or more matches of
  204. Xthat form.
  205. X
  206. X.Ti 
  207. X[6]    \fB+\fR    Same as [5], except it matches one or more.
  208. X
  209. X.Ti 
  210. X[7]        A regular expression in the form [1] to [10], enclosed
  211. Xas \\(\fIform\fR\\) matches what form matches. The enclosure
  212. Xcreates a set of tags, used for [8] and for
  213. Xpattern substitution in
  214. X.I re_subs. 
  215. XThe tagged forms are numbered
  216. Xstarting from 1.
  217. X
  218. X.Ti 
  219. X[8]        A \\ followed by a digit 1 to 9 matches whatever a
  220. Xpreviously tagged regular expression ([7]) matched.
  221. X
  222. X.Ti
  223. X[9]    \fB\\<\fR    Matches the beginning of a \fIword\fR,
  224. Xthat is, an empty string followed by a
  225. Xletter, digit, or _ and not preceded by
  226. Xa letter, digit, or _ .
  227. X.Ti
  228. X    \fB\\>\fR    Matches the end of a \fIword\fR,
  229. Xthat is, an empty string preceded
  230. Xby a letter, digit, or _ , and not
  231. Xfollowed by a letter, digit, or _ .
  232. X
  233. X.Ti 
  234. X[10]        A composite regular expression 
  235. X\fIxy\fR where \fIx\fR and \fIy\fR
  236. Xare in the form of [1] to [10] matches the longest
  237. Xmatch of \fIx\fR followed by a match for \fIy\fR.
  238. X
  239. X.Ti 
  240. X[11]    \fB^ $\fR    a regular expression starting with a \fB^\fR character
  241. Xand/or ending with a \fB$\fR character, restricts the
  242. Xpattern matching to the beginning of the line,
  243. Xand/or the end of line [anchors]. Elsewhere in the
  244. Xpattern, \fB^\fR and \fB$\fR are treated as ordinary characters.
  245. X.if n .in -1.6i
  246. X.if t .in -1i
  247. X
  248. X.PP
  249. X.I Re_exec
  250. Xexecutes the internal form produced by
  251. X.I re_comp
  252. Xand searches the argument string for the regular expression described
  253. Xby the internal
  254. Xform. 
  255. X.I Re_exec
  256. Xreturns 1 if the last regular expression pattern is matched within the string,
  257. X0 if no match is found. In case of an internal error (corrupted internal
  258. Xform), 
  259. X.I re_exec 
  260. Xcalls the user-supplied
  261. X.I re_fail
  262. Xand returns 0.
  263. X.PP
  264. XThe strings passed to both
  265. X.I re_comp
  266. Xand
  267. X.I re_exec
  268. Xmay have trailing or embedded newline characters. The strings 
  269. Xmust be terminated by nulls.
  270. X.PP
  271. X.I Re_subs
  272. Xdoes
  273. X.IR ed -style
  274. Xpattern substitution, after a successful match is found by
  275. X.I re_exec.
  276. XThe source string parameter to
  277. X.I re_subs
  278. Xis copied to the destination string with the following interpretation;
  279. X.sp
  280. X.if n .in +1.6i
  281. X.if t .in +1i
  282. X.Ti
  283. X[1]    &    Substitute the entire matched string in the destination.
  284. X
  285. X.Ti
  286. X[2]    \\\fIn\fR    Substitute the substring matched by a tagged subpattern
  287. Xnumbered \fIn\fR, where \fIn\fR is between 1 to 9, inclusive.
  288. X
  289. X.Ti
  290. X[3]    \\\fIchar\fR    Treat the next character literally,
  291. Xunless the character is a digit ([2]).
  292. X.if n .in -1.6i
  293. X.if t .in -1i
  294. X
  295. X.PP
  296. XIf the copy operation with the substitutions is successful,
  297. X.I re_subs
  298. Xreturns 1.
  299. XIf the source string is corrupted, or the last call to
  300. X.I re_exec
  301. Xfails, it returns 0.
  302. X
  303. X.I Re_modw
  304. Xis used to 
  305. Xadd new characters into an internal table to
  306. Xchange the re_exec's understanding of what
  307. Xa \fIword\fR should look like, when matching with \fB\\<\fR and \fB\\>\fR
  308. Xconstructs. If the string parameter is 0 or null string,
  309. Xthe table is reset back to the default, which contains \fBA-Z a-z 0-9 _\fR .
  310. X
  311. X.I Re_fail
  312. Xis a user-supplied routine to handle internal errors.
  313. X.I re_exec
  314. Xcalls
  315. X.I re_fail
  316. Xwith an error message string, and the opcode character that caused the error.
  317. XThe default
  318. X.I re_fail
  319. Xroutine simply prints the message and the opcode character to
  320. X.I stderr
  321. Xand invokes
  322. X.IR exit (2).
  323. X.SH EXAMPLES
  324. XIn the examples below, the
  325. X.I dfaform
  326. Xdescribes the internal form after the pattern is compiled. For additional
  327. Xdetails, refer to the sources.
  328. X.PP
  329. X.ta 0.5i +0.5i +0.5i
  330. X.nf
  331. Xfoo*.*
  332. X    dfaform:    CHR f CHR o CLO CHR o END CLO ANY END END
  333. X    matches:    \fIfo foo fooo foobar fobar foxx ...\fR
  334. X
  335. Xfo[ob]a[rz]
  336. X    dfaform:    CHR f CHR o CCL 2 o b CHR a CCL 2 r z END
  337. X    matches:    \fIfobar fooar fobaz fooaz\fR
  338. X
  339. Xfoo\\\\+
  340. X    dfaform:    CHR f CHR o CHR o CHR \\ CLO CHR \\ END END
  341. X    matches:    \fIfoo\\ foo\\\\ foo\\\\\\  ...\fR
  342. X
  343. X\\(foo\\)[1-3]\\1    (same as foo[1-3]foo, but takes less internal space)
  344. X    dfaform:    BOT 1 CHR f CHR o CHR o EOT 1 CCL 3 1 2 3 REF 1 END
  345. X    matches:    \fIfoo1foo foo2foo foo3foo\fR
  346. X
  347. X\\(fo.*\\)-\\1
  348. X    dfaform:    BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
  349. X    matches:    \fIfoo-foo fo-fo fob-fob foobar-foobar ...\fR
  350. X.SH DIAGNOSTICS
  351. X.I Re_comp
  352. Xreturns one of the following strings if an error occurs:
  353. X.PP
  354. X.nf
  355. X.in +0.5i
  356. X\fINo previous regular expression,
  357. XEmpty closure,
  358. XIllegal closure,
  359. XCyclical reference,
  360. XUndetermined reference,
  361. XUnmatched \e(,
  362. XMissing ],
  363. XNull pattern inside \e(\e),
  364. XNull pattern inside \e<\e>,
  365. XToo many \e(\e) pairs,
  366. XUnmatched \e)\fP.
  367. X.in -0.5i
  368. X.fi
  369. X.SH REFERENCES
  370. X.if n .ta 3i
  371. X.if t .ta 1.8i
  372. X.nf
  373. X\fISoftware tools\fR    Kernighan & Plauger
  374. X\fISoftware tools in Pascal\fR    Kernighan & Plauger
  375. X\fIGrep sources\fR [rsx-11 C dist]    David Conroy
  376. X\fIEd - text editor\fR    Unix Programmer's Manual
  377. X\fIAdvanced editing on Unix\fR    B. W. Kernighan
  378. X\fIRegExp sources\fR    Henry Spencer
  379. X.fi
  380. X.SH "HISTORY AND NOTES"
  381. XThese routines are derived from various implementations
  382. Xfound in 
  383. X.I "Software Tools"
  384. Xbooks, and David Conroy's 
  385. X.I grep. 
  386. XThey are NOT derived from licensed/restricted software.
  387. XFor more interesting/academic/complicated implementations,
  388. Xsee Henry Spencer's 
  389. X.I regexp 
  390. Xroutines (V8), or 
  391. X.I "GNU Emacs"
  392. Xpattern
  393. Xmatching module.
  394. X.PP
  395. XThe
  396. X.I re_comp
  397. Xand
  398. X.I re_exec
  399. Xroutines perform
  400. X.I almost
  401. Xas well as their licensed counterparts, sometimes better. 
  402. XIn very few instances, they
  403. Xare about 10% to 15% slower.
  404. X.SH AUTHOR
  405. XOzan S. Yigit (oz)
  406. X.br
  407. Xusenet: utzoo!yetti!oz
  408. X.br
  409. Xbitnet: oz@yusol || oz@yuyetti
  410. X.SH "SEE ALSO"
  411. Xed(1), ex(1), egrep(1), fgrep(1), grep(1), regex(3)
  412. X.SH BUGS
  413. XThese routines are \fIPublic Domain\fR. You can get them
  414. Xin source.
  415. X.br
  416. XThe internal storage for the \fIdfa form\fR is not checked for
  417. Xoverflows. Currently, it is 1024 bytes.
  418. X.br
  419. XOthers, no doubt.
  420. SHAR_EOF
  421. if test 7847 -ne "`wc -c 'regex.3'`"
  422. then
  423.     echo shar: error transmitting "'regex.3'" '(should have been 7847 characters)'
  424. fi
  425. echo shar: extracting "'regex.c'" '(18779 characters)'
  426. if test -f 'regex.c'
  427. then
  428.     echo shar: over-writing existing file "'regex.c'"
  429. fi
  430. sed 's/^X//' << \SHAR_EOF > 'regex.c'
  431. X/*
  432. X * regex - Regular expression pattern matching
  433. X *         and replacement
  434. X *
  435. X *
  436. X * By:  Ozan S. Yigit (oz)
  437. X *      Dept. of Computer Science
  438. X *      York University
  439. X *
  440. X *
  441. X * These routines are the PUBLIC DOMAIN equivalents 
  442. X * of regex routines as found in 4.nBSD UN*X, with minor
  443. X * extensions.
  444. X *
  445. X * These routines are derived from various implementations
  446. X * found in software tools books, and Conroy's grep. They
  447. X * are NOT derived from licensed/restricted software.
  448. X * For more interesting/academic/complicated implementations,
  449. X * see Henry Spencer's regexp routines, or GNU Emacs pattern
  450. X * matching module.
  451. X *
  452. X * Routines:
  453. X *      re_comp:        compile a regular expression into
  454. X *                      a DFA.
  455. X *
  456. X *            char *re_comp(s)
  457. X *            char *s;
  458. X *
  459. X *      re_exec:        execute the DFA to match a pattern.
  460. X *
  461. X *            int re_exec(s)
  462. X *            char *s;
  463. X *
  464. X *    re_modw        change re_exec's understanding of what
  465. X *            a "word" looks like (for \< and \>)
  466. X *            by adding into the hidden word-character 
  467. X *            table.
  468. X *
  469. X *            void re_modw(s)
  470. X *            char *s;
  471. X *
  472. X *      re_subs:    substitute the matched portions in
  473. X *                  a new string.
  474. X *
  475. X *            int re_subs(src, dst)
  476. X *            char *src;
  477. X *            char *dst;
  478. X *
  479. X *    re_fail:    failure routine for re_exec.
  480. X *
  481. X *            void re_fail(msg, op)
  482. X *            char *msg;
  483. X *            char op;
  484. X *  
  485. X * Regular Expressions:
  486. X *
  487. X *      [1]     char    matches itself, unless it is a special
  488. X *                      character (metachar): . \ [ ] * + ^ $
  489. X *
  490. X *      [2]     .       matches any character.
  491. X *
  492. X *      [3]     \       matches the character following it, except
  493. X *            when followed by a left or right round bracket,
  494. X *            a digit 1 to 9 or a left or right angle bracket. 
  495. X *            (see [7], [8] and [9])
  496. X *            It is used as an escape character for all 
  497. X *            other meta-characters, and itself. When used
  498. X *            in a set ([4]), it is treated as an ordinary
  499. X *            character.
  500. X *
  501. X *      [4]     [set]   matches one of the characters in the set.
  502. X *                      If the first character in the set is "^",
  503. X *                      it matches a character NOT in the set. A
  504. X *                      shorthand S-E is used to specify a set of
  505. X *                      characters S upto E, inclusive. The special
  506. X *                      characters "]" and "-" have no special
  507. X *                      meaning if they appear as the first chars
  508. X *                      in the set.
  509. X *                      examples:        match:
  510. X *
  511. X *                              [a-z]    any lowercase alpha
  512. X *
  513. X *                              [^]-]    any char except ] and -
  514. X *
  515. X *                              [^A-Z]   any char except uppercase
  516. X *                                       alpha
  517. X *
  518. X *                              [a-zA-Z] any alpha
  519. X *
  520. X *      [5]     *       any regular expression form [1] to [4], followed by
  521. X *                      closure char (*) matches zero or more matches of
  522. X *                      that form.
  523. X *
  524. X *      [6]     +       same as [5], except it matches one or more.
  525. X *
  526. X *      [7]             a regular expression in the form [1] to [10], enclosed
  527. X *                      as \(form\) matches what form matches. The enclosure
  528. X *                      creates a set of tags, used for [8] and for
  529. X *                      pattern substution. The tagged forms are numbered
  530. X *            starting from 1.
  531. X *
  532. X *      [8]             a \ followed by a digit 1 to 9 matches whatever a
  533. X *                      previously tagged regular expression ([7]) matched.
  534. X *
  535. X *    [9]    \<    a regular expression starting with a \< construct
  536. X *        \>    and/or ending with a \> construct, restricts the
  537. X *            pattern matching to the beginning of a word, and/or
  538. X *            the end of a word. A word is defined to be a character
  539. X *            string beginning and/or ending with the characters
  540. X *            A-Z a-z 0-9 and _. It must also be preceded and/or
  541. X *            followed by any character outside those mentioned.
  542. X *
  543. X *      [10]            a composite regular expression xy where x and y
  544. X *                      are in the form [1] to [10] matches the longest
  545. X *                      match of x followed by a match for y.
  546. X *
  547. X *      [11]    ^    a regular expression starting with a ^ character
  548. X *        $    and/or ending with a $ character, restricts the
  549. X *                      pattern matching to the beginning of the line,
  550. X *                      or the end of line. [anchors] Elsewhere in the
  551. X *            pattern, ^ and $ are treated as ordinary characters.
  552. X *
  553. X *
  554. X * Acknowledgements:
  555. X *
  556. X *    HCR's Hugh Redelmeier has been most helpful in various
  557. X *    stages of development. He convinced me to include BOW
  558. X *    and EOW constructs, originally invented by Rob Pike at
  559. X *    the University of Toronto.
  560. X *
  561. X * References:
  562. X *              Software tools            Kernighan & Plauger
  563. X *              Software tools in Pascal        Kernighan & Plauger
  564. X *              Grep [rsx-11 C dist]            David Conroy
  565. X *        ed - text editor        Un*x Programmer's Manual
  566. X *        Advanced editing on Un*x    B. W. Kernighan
  567. X *        RegExp routines            Henry Spencer
  568. X *
  569. X * Notes:
  570. X *
  571. X *    This implementation uses a bit-set representation for character
  572. X *    classes for speed and compactness. Each character is represented 
  573. X *    by one bit in a 128-bit block. Thus, CCL or NCL always takes a 
  574. X *    constant 16 bytes in the internal dfa, and re_exec does a single
  575. X *    bit comparison to locate the character in the set.
  576. X *
  577. X * Examples:
  578. X *
  579. X *    pattern:    foo*.*
  580. X *    compile:    CHR f CHR o CLO CHR o END CLO ANY END END
  581. X *    matches:    fo foo fooo foobar fobar foxx ...
  582. X *
  583. X *    pattern:    fo[ob]a[rz]    
  584. X *    compile:    CHR f CHR o CCL 2 o b CHR a CCL bitset END
  585. X *    matches:    fobar fooar fobaz fooaz
  586. X *
  587. X *    pattern:    foo\\+
  588. X *    compile:    CHR f CHR o CHR o CHR \ CLO CHR \ END END
  589. X *    matches:    foo\ foo\\ foo\\\  ...
  590. X *
  591. X *    pattern:    \(foo\)[1-3]\1    (same as foo[1-3]foo)
  592. X *    compile:    BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
  593. X *    matches:    foo1foo foo2foo foo3foo
  594. X *
  595. X *    pattern:    \(fo.*\)-\1
  596. X *    compile:    BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
  597. X *    matches:    foo-foo fo-fo fob-fob foobar-foobar ...
  598. X * 
  599. X */
  600. X
  601. X#define MAXDFA  1024
  602. X#define MAXTAG  10
  603. X
  604. X#define OKP     1
  605. X#define NOP     0
  606. X
  607. X#define CHR     1
  608. X#define ANY     2
  609. X#define CCL     3
  610. X#define NCL     4
  611. X#define BOL     5
  612. X#define EOL     6
  613. X#define BOT     7
  614. X#define EOT     8
  615. X#define BOW    9
  616. X#define EOW    10
  617. X#define REF     11
  618. X#define CLO     12
  619. X
  620. X#define END     0
  621. X
  622. X/*
  623. X * The following defines are not meant
  624. X * to be changeable. They are for readibility
  625. X * only.
  626. X *
  627. X */
  628. X#define MAXCHR    128
  629. X#define CHRBIT    8
  630. X#define BITBLK    MAXCHR/CHRBIT
  631. X#define BLKIND    0170
  632. X#define BITIND    07
  633. X
  634. X#define ASCIIB    0177
  635. X
  636. Xtypedef /*unsigned*/ char CHAR;
  637. X
  638. Xstatic int  tagstk[MAXTAG];             /* subpat tag stack..*/
  639. Xstatic CHAR dfa[MAXDFA];        /* automaton..       */
  640. Xstatic int  sta = NOP;                   /* status of lastpat */
  641. X
  642. Xstatic CHAR bittab[BITBLK];        /* bit table for CCL */
  643. X
  644. Xstatic void
  645. Xchset(c) register CHAR c; { bittab[((c)&BLKIND)>>3] |= 1<<((c)&BITIND); }
  646. X
  647. X#define badpat(x)    return(*dfa = END, x)
  648. X#define store(x)    *mp++ = x
  649. Xchar *     
  650. Xre_comp(pat)
  651. Xchar *pat;
  652. X{
  653. X    register char *p;               /* pattern pointer   */
  654. X    register CHAR *mp=dfa;          /* dfa pointer       */
  655. X    register CHAR *lp;              /* saved pointer..   */
  656. X    register CHAR *sp=dfa;          /* another one..     */
  657. X
  658. X    register int tagi = 0;          /* tag stack index   */
  659. X    register int tagc = 1;          /* actual tag count  */
  660. X
  661. X    register int n;
  662. X    int c1, c2;
  663. X        
  664. X    if (!pat || !*pat)
  665. X        if (sta)
  666. X            return(0);
  667. X        else
  668. X            badpat("No previous regular expression");
  669. X    sta = NOP;
  670. X
  671. X    for (p = pat; *p; p++) {
  672. X        lp = mp;
  673. X        switch(*p) {
  674. X
  675. X        case '.':               /* match any char..  */
  676. X            store(ANY);
  677. X            break;
  678. X
  679. X        case '^':               /* match beginning.. */
  680. X            if (p == pat)
  681. X                store(BOL);
  682. X            else {
  683. X                store(CHR);
  684. X                store(*p);
  685. X            }
  686. X            break;
  687. X
  688. X        case '$':               /* match endofline.. */
  689. X            if (!*(p+1))
  690. X                store(EOL);
  691. X            else {
  692. X                store(CHR);
  693. X                store(*p);
  694. X            }
  695. X            break;
  696. X
  697. X        case '[':               /* match char class..*/
  698. X
  699. X            if (*++p == '^') {
  700. X                store(NCL);
  701. X                p++;
  702. X            }
  703. X            else
  704. X                store(CCL);
  705. X
  706. X            if (*p == '-')        /* real dash */
  707. X                chset(*p++);
  708. X            if (*p == ']')        /* real brac */
  709. X                chset(*p++);
  710. X            while (*p && *p != ']') {
  711. X                if (*p == '-' && *(p+1) && *(p+1) != ']') {
  712. X                    p++;
  713. X                    c1 = *(p-2) + 1;
  714. X                    c2 = *p++;
  715. X                    while (c1 <= c2)
  716. X                        chset(c1++);
  717. X                }
  718. X#ifdef EXTEND
  719. X                else if (*p == '\\' && *(p+1)) {
  720. X                    p++;
  721. X                    chset(*p++);
  722. X                }
  723. X#endif
  724. X                else
  725. X                    chset(*p++);
  726. X            }
  727. X            if (!*p)
  728. X                badpat("Missing ]");
  729. X
  730. X            for (n = 0; n < BITBLK; bittab[n++] = (char) 0)
  731. X                store(bittab[n]);
  732. X    
  733. X            break;
  734. X
  735. X        case '*':               /* match 0 or more.. */
  736. X        case '+':               /* match 1 or more.. */
  737. X            if (p == pat)
  738. X                badpat("Empty closure");
  739. X            lp = sp;                /* previous opcode */
  740. X            if (*lp == CLO)         /* equivalence..   */
  741. X                break;
  742. X            switch(*lp) {
  743. X
  744. X            case BOL:
  745. X            case BOT:
  746. X            case EOT:
  747. X            case BOW:
  748. X            case EOW:
  749. X            case REF:
  750. X                badpat("Illegal closure");
  751. X            default:
  752. X                break;
  753. X            }
  754. X
  755. X            if (*p == '+')
  756. X                for (sp = mp; lp < sp; lp++)
  757. X                    store(*lp);
  758. X
  759. X            store(END);
  760. X            store(END);
  761. X            sp = mp;
  762. X            while (--mp > lp)
  763. X                *mp = mp[-1];
  764. X            store(CLO);
  765. X            mp = sp;
  766. X            break;
  767. X
  768. X        case '\\':              /* tags, backrefs .. */
  769. X            switch(*++p) {
  770. X
  771. X            case '(':
  772. X                if (tagc < MAXTAG) {
  773. X                    tagstk[++tagi] = tagc;
  774. X                    store(BOT);
  775. X                    store(tagc++);
  776. X                }
  777. X                else
  778. X                    badpat("Too many \\(\\) pairs");
  779. X                break;
  780. X            case ')':
  781. X                if (*sp == BOT)
  782. X                    badpat("Null pattern inside \\(\\)");
  783. X                if (tagi > 0) {
  784. X                    store(EOT);
  785. X                    store(tagstk[tagi--]);
  786. X                }
  787. X                else
  788. X                    badpat("Unmatched \\)");
  789. X                break;
  790. X            case '<':
  791. X                store(BOW);
  792. X                break;
  793. X            case '>':
  794. X                if (*sp == BOW)
  795. X                    badpat("Null pattern inside \\<\\>");
  796. X                store(EOW);
  797. X                break;
  798. X            case '1':
  799. X            case '2':
  800. X            case '3':
  801. X            case '4':
  802. X            case '5':
  803. X            case '6':
  804. X            case '7':
  805. X            case '8':
  806. X            case '9':
  807. X                n = *p-'0';
  808. X                if (tagi > 0 && tagstk[tagi] == n)
  809. X                    badpat("Cyclical reference");
  810. X                if (tagc > n) {
  811. X                    store(REF);
  812. X                    store(n);
  813. X                }
  814. X                else
  815. X                    badpat("Undetermined reference");
  816. X                break;
  817. X#ifdef EXTEND
  818. X            case 'b':
  819. X                store(CHR);
  820. X                store('\b');
  821. X                break;
  822. X            case 'n':
  823. X                store(CHR);
  824. X                store('\n');
  825. X                break;
  826. X            case 'f':
  827. X                store(CHR);
  828. X                store('\f');
  829. X                break;
  830. X            case 'r':
  831. X                store(CHR);
  832. X                store('\r');
  833. X                break;
  834. X            case 't':
  835. X                store(CHR);
  836. X                store('\t');
  837. X                break;
  838. X#endif
  839. X            default:
  840. X                store(CHR);
  841. X                store(*p);
  842. X            }
  843. X            break;
  844. X
  845. X        default :               /* an ordinary char  */
  846. X            store(CHR);
  847. X            store(*p);
  848. X            break;
  849. X        }
  850. X        sp = lp;
  851. X    }
  852. X    if (tagi > 0)
  853. X        badpat("Unmatched \\(");
  854. X    store(END);
  855. X    sta = OKP;
  856. X    return(0);
  857. X}
  858. X
  859. X
  860. Xstatic char *bol;
  861. Xstatic char *bopat[MAXTAG];
  862. Xstatic char *eopat[MAXTAG];
  863. Xchar *pmatch();
  864. X
  865. X/*
  866. X * re_exec:
  867. X *     execute dfa to find a match.
  868. X *
  869. X *    special cases: (dfa[0])    
  870. X *        BOL
  871. X *            Match only once, starting from the
  872. X *            beginning.
  873. X *        CHR
  874. X *            First locate the character without
  875. X *            calling pmatch, and if found, call
  876. X *            pmatch for the remaining string.
  877. X *        END
  878. X *            re_comp failed, poor luser did not
  879. X *            check for it. Fail fast.
  880. X *
  881. X *    If a match is found, bopat[0] and eopat[0] are set
  882. X *    to the beginning and the end of the matched fragment,
  883. X *    respectively.
  884. X *
  885. X */
  886. X
  887. Xint
  888. Xre_exec(lp)
  889. Xregister char *lp;
  890. X{
  891. X    register char c;
  892. X    register char *ep = 0;
  893. X    register CHAR *ap = dfa;
  894. X
  895. X    bol = lp;
  896. X
  897. X    bopat[0] = 0;
  898. X    bopat[1] = 0;
  899. X    bopat[2] = 0;
  900. X    bopat[3] = 0;
  901. X    bopat[4] = 0;
  902. X    bopat[5] = 0;
  903. X    bopat[6] = 0;
  904. X    bopat[7] = 0;
  905. X    bopat[8] = 0;
  906. X    bopat[9] = 0;
  907. X
  908. X    switch(*ap) {
  909. X
  910. X    case BOL:            /* anchored: match from BOL only */
  911. X        ep = pmatch(lp,ap);
  912. X        break;
  913. X    case CHR:            /* ordinary char: locate it fast */
  914. X        c = *(ap+1);
  915. X        while (*lp && *lp != c)
  916. X            lp++;
  917. X        if (!*lp)        /* if EOS, fail, else fall thru. */
  918. X            return(0);
  919. X    default:            /* regular matching all the way. */
  920. X        while (*lp) {
  921. X            if ((ep = pmatch(lp,ap)))
  922. X                break;
  923. X            lp++;
  924. X        }
  925. X        break;
  926. X    case END:            /* munged automaton. fail always */
  927. X        return(0);
  928. X    }
  929. X    if (!ep)
  930. X        return(0);
  931. X
  932. X    bopat[0] = lp;
  933. X    eopat[0] = ep;
  934. X    return(1);
  935. X}
  936. X
  937. X/* 
  938. X * pmatch: 
  939. X *    internal routine for the hard part
  940. X *
  941. X *     This code is mostly snarfed from an early
  942. X *     grep written by David Conroy. The backref and
  943. X *     tag stuff, and various other mods are by oZ.
  944. X *
  945. X *    special cases: (dfa[n], dfa[n+1])
  946. X *        CLO ANY
  947. X *            We KNOW ".*" will match ANYTHING
  948. X *            upto the end of line. Thus, go to
  949. X *            the end of line straight, without
  950. X *            calling pmatch recursively. As in
  951. X *            the other closure cases, the remaining
  952. X *            pattern must be matched by moving
  953. X *            backwards on the string recursively,
  954. X *            to find a match for xy (x is ".*" and 
  955. X *            y is the remaining pattern) where
  956. X *            the match satisfies the LONGEST match
  957. X *            for x followed by a match for y.
  958. X *        CLO CHR
  959. X *            We can again scan the string forward
  960. X *            for the single char without recursion, 
  961. X *            and at the point of failure, we execute 
  962. X *            the remaining dfa recursively, as
  963. X *            described above.
  964. X *
  965. X *    At the end of a successful match, bopat[n] and eopat[n]
  966. X *    are set to the beginning and end of subpatterns matched
  967. X *    by tagged expressions (n = 1 to 9).    
  968. X *
  969. X */
  970. X
  971. Xextern void re_fail();
  972. X
  973. X/*
  974. X * character classification table for word boundary
  975. X * operators BOW and EOW. the reason for not using 
  976. X * ctype macros is that we can let the user add into 
  977. X * our own table. see re_modw. This table is not in
  978. X * the bitset form, since we may wish to extend it
  979. X * in the future for other character classifications. 
  980. X *
  981. X *    TRUE for 0-9 A-Z a-z _
  982. X */
  983. Xstatic char chrtyp[MAXCHR] = {
  984. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  985. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  986. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  987. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  988. X    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 
  989. X    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 
  990. X    0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 
  991. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  992. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  993. X    1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 
  994. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  995. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  996. X    1, 1, 1, 0, 0, 0, 0, 0
  997. X    };
  998. X
  999. X#define inascii(x)    (0177&(x))
  1000. X#define iswordc(x)     chrtyp[inascii(x)]
  1001. X#define isinset(x,y)     ((x)[((y)&BLKIND)>>3] & (1<<((y)&BITIND)))
  1002. X
  1003. X/*
  1004. X * skip values for CLO XXX to skip past the closure
  1005. X *
  1006. X */
  1007. X
  1008. X#define ANYSKIP    2     /* CLO ANY END ...       */
  1009. X#define CHRSKIP    3    /* CLO CHR chr END ...       */
  1010. X#define CCLSKIP 18    /* CLO CCL 16bytes END ... */
  1011. X
  1012. Xstatic char *
  1013. Xpmatch(lp, ap)
  1014. Xregister char *lp;
  1015. Xregister CHAR *ap;
  1016. X{
  1017. X    register char *e;        /* extra pointer for CLO */
  1018. X    register char *bp;        /* beginning of subpat.. */
  1019. X    register char *ep;        /* ending of subpat..     */
  1020. X    register int op, c, n;
  1021. X    char *are;            /* to save the line ptr. */
  1022. X
  1023. X    while ((op = *ap++) != END)
  1024. X        switch(op) {
  1025. X
  1026. X        case CHR:
  1027. X            if (*lp++ != *ap++)
  1028. X                return(0);
  1029. X            break;
  1030. X        case ANY:
  1031. X            if (!*lp++)
  1032. X                return(0);
  1033. X            break;
  1034. X        case CCL:
  1035. X            c = *lp++;
  1036. X            if (!isinset(ap,c))
  1037. X                return(0);
  1038. X            ap += BITBLK;
  1039. X            break;
  1040. X        case NCL:
  1041. X            c = *lp++;
  1042. X            if (isinset(ap,c))
  1043. X                return(0);
  1044. X            ap += BITBLK;
  1045. X            break;
  1046. X        case BOL:
  1047. X            if (lp != bol)
  1048. X                return(0);
  1049. X            break;
  1050. X        case EOL:
  1051. X            if (*lp)
  1052. X                return(0);
  1053. X            break;
  1054. X        case BOT:
  1055. X            bopat[*ap++] = lp;
  1056. X            break;
  1057. X        case EOT:
  1058. X            eopat[*ap++] = lp;
  1059. X            break;
  1060. X         case BOW:
  1061. X            if (!(lp!=bol && iswordc(lp[-1])) && iswordc(*lp))
  1062. X                break;
  1063. X            return(0);
  1064. X        case EOW:
  1065. X            if ((lp!=bol && iswordc(lp[-1])) && !iswordc(*lp))
  1066. X                break;
  1067. X            return(0);
  1068. X        case REF:
  1069. X            n = *ap++;
  1070. X            bp = bopat[n];
  1071. X            ep = eopat[n];
  1072. X            while (bp < ep)
  1073. X                if (*bp++ != *lp++)
  1074. X                    return(0);
  1075. X            break;
  1076. X        case CLO:
  1077. X            are = lp;
  1078. X            switch(*ap) {
  1079. X
  1080. X            case ANY:
  1081. X                while (*lp)
  1082. X                    lp++;
  1083. X                n = ANYSKIP;
  1084. X                break;
  1085. X            case CHR:
  1086. X                c = *(ap+1);
  1087. X                while (*lp && c == *lp)
  1088. X                    lp++;
  1089. X                n = CHRSKIP;
  1090. X                break;
  1091. X            case CCL:
  1092. X            case NCL:
  1093. X                while (*lp && (e = pmatch(lp, ap)))
  1094. X                    lp = e;
  1095. X                n = CCLSKIP;
  1096. X                break;
  1097. X            default:
  1098. X                re_fail("closure: bad dfa.", *ap);
  1099. X                return(0);
  1100. X            }
  1101. X
  1102. X            ap += n;
  1103. X
  1104. X            while (lp >= are) {
  1105. X                if (e = pmatch(lp, ap))
  1106. X                    return(e);
  1107. X                --lp;
  1108. X            }
  1109. X            return(0);
  1110. X        default:
  1111. X            re_fail("re_exec: bad dfa.", op);
  1112. X            return(0);
  1113. X        }
  1114. X    return(lp);
  1115. X}
  1116. X
  1117. X/*
  1118. X * re_modw:
  1119. X *    add new characters into the word table to
  1120. X *    change the re_exec's understanding of what
  1121. X *    a word should look like. Note that we only
  1122. X *    accept additions into the word definition.
  1123. X *
  1124. X *    If the string parameter is 0 or null string,
  1125. X *    the table is reset back to the default, which
  1126. X *    contains A-Z a-z 0-9 _. [We use the compact
  1127. X *    bitset representation for the default table]
  1128. X *
  1129. X */
  1130. X
  1131. Xstatic char deftab[16] = {    
  1132. X    0, 0, 0, 0, 0, 0, 377, 003, 376, 377, 377, 207,  
  1133. X    376, 377, 377, 007 
  1134. X}; 
  1135. X
  1136. Xvoid
  1137. Xre_modw(s)
  1138. Xregister char *s;
  1139. X{
  1140. X    register int i;
  1141. X
  1142. X    if (!s || !*s) {
  1143. X        for (i = 0; i < MAXCHR; i++)
  1144. X            if (!isinset(deftab,i))
  1145. X                iswordc(i) = 0;
  1146. X    }
  1147. X    else
  1148. X        while(*s)
  1149. X            iswordc(*s++) = 1;
  1150. X}
  1151. X
  1152. X/*
  1153. X * re_subs:
  1154. X *    substitute the matched portions of the src in
  1155. X *    dst.
  1156. X *
  1157. X *    &    substitute the entire matched pattern.
  1158. X *
  1159. X *    \digit    substitute a subpattern, with the given
  1160. X *        tag number. Tags are numbered from 1 to
  1161. X *        9. If the particular tagged subpattern
  1162. X *        does not exist, null is substituted.
  1163. X *
  1164. X */
  1165. Xint
  1166. Xre_subs(src, dst)
  1167. Xregister char *src;
  1168. Xregister char *dst;
  1169. X{
  1170. X    register char c;
  1171. X    register int  pin;
  1172. X    register char *bp;
  1173. X    register char *ep;
  1174. X
  1175. X    if (!*src || !bopat[0])
  1176. X        return(0);
  1177. X
  1178. X    while (c = *src++) {
  1179. X        switch(c) {
  1180. X
  1181. X        case '&':
  1182. X            pin = 0;
  1183. X            break;
  1184. X
  1185. X        case '\\':
  1186. X            c = *src++;
  1187. X            if (c >= '0' && c <= '9') {
  1188. X                pin = c - '0';
  1189. X                break;
  1190. X            }
  1191. X            
  1192. X        default:
  1193. X            *dst++ = c;
  1194. X            continue;
  1195. X        }
  1196. X
  1197. X        if ((bp = bopat[pin]) && (ep = eopat[pin])) {
  1198. X            while (*bp && bp < ep)
  1199. X                *dst++ = *bp++;
  1200. X            if (bp < ep)
  1201. X                return(0);
  1202. X        }
  1203. X    }
  1204. X    *dst = (char) 0;
  1205. X    return(1);
  1206. X}
  1207. X            
  1208. X#ifdef DEBUG
  1209. X/*
  1210. X * symbolic - produce a symbolic dump of the
  1211. X *            dfa
  1212. X */
  1213. Xsymbolic(s) 
  1214. Xchar *s;
  1215. X{
  1216. X    printf("pattern: %s\n", s);
  1217. X    printf("dfacode:\n");
  1218. X    dfadump(dfa);
  1219. X}
  1220. X
  1221. Xstatic    
  1222. Xdfadump(ap)
  1223. XCHAR *ap;
  1224. X{
  1225. X    register int n;
  1226. X
  1227. X    while (*ap != END)
  1228. X        switch(*ap++) {
  1229. X        case CLO:
  1230. X            printf("CLOSURE");
  1231. X            dfadump(ap);
  1232. X            switch(*ap) {
  1233. X            case CHR:
  1234. X                n = CHRSKIP;
  1235. X                break;
  1236. X            case ANY:
  1237. X                n = ANYSKIP;
  1238. X                break;
  1239. X            case CCL:
  1240. X            case NCL:
  1241. X                n = CCLSKIP;
  1242. X                break;
  1243. X            }
  1244. X            ap += n;
  1245. X            break;
  1246. X        case CHR:
  1247. X            printf("\tCHR %c\n",*ap++);
  1248. X            break;
  1249. X        case ANY:
  1250. X            printf("\tANY .\n");
  1251. X            break;
  1252. X        case BOL:
  1253. X            printf("\tBOL -\n");
  1254. X            break;
  1255. X        case EOL:
  1256. X            printf("\tEOL -\n");
  1257. X            break;
  1258. X        case BOT:
  1259. X            printf("BOT: %d\n",*ap++);
  1260. X            break;
  1261. X        case EOT:
  1262. X            printf("EOT: %d\n",*ap++);
  1263. X            break;
  1264. X        case BOW:
  1265. X            printf("BOW\n");
  1266. X            break;
  1267. X        case EOW:
  1268. X            printf("EOW\n");
  1269. X            break;
  1270. X        case REF:
  1271. X            printf("REF: %d\n",*ap++);
  1272. X            break;
  1273. X        case CCL:
  1274. X            printf("\tCCL [");
  1275. X            for (n = 0; n < MAXCHR; n++)
  1276. X                if (isinset(ap,(CHAR)n))
  1277. X                    printf("%c",n);
  1278. X            printf("]\n");
  1279. X            ap += BITBLK;
  1280. X            break;
  1281. X        case NCL:
  1282. X            printf("\tNCL [");
  1283. X            for (n = 0; n < MAXCHR; n++)
  1284. X                if (isinset(ap,(CHAR)n))
  1285. X                    printf("%c",n);
  1286. X            printf("]\n");
  1287. X            ap += BITBLK;
  1288. X            break;
  1289. X        default:
  1290. X            printf("bad dfa. opcode %o\n", ap[-1]);
  1291. X            exit(1);
  1292. X            break;
  1293. X        }
  1294. X}
  1295. X#endif
  1296. SHAR_EOF
  1297. if test 18779 -ne "`wc -c 'regex.c'`"
  1298. then
  1299.     echo shar: error transmitting "'regex.c'" '(should have been 18779 characters)'
  1300. fi
  1301. echo shar: extracting "'re_fail.c'" '(292 characters)'
  1302. if test -f 're_fail.c'
  1303. then
  1304.     echo shar: over-writing existing file "'re_fail.c'"
  1305. fi
  1306. sed 's/^X//' << \SHAR_EOF > 're_fail.c'
  1307. X
  1308. X#ifdef vms
  1309. X#include stdio
  1310. X#else
  1311. X#include <stdio.h>
  1312. X#endif
  1313. X
  1314. X/* 
  1315. X * re_fail:
  1316. X *    internal error handler for re_exec.
  1317. X *
  1318. X *    should probably do something like a
  1319. X *    longjump to recover gracefully.
  1320. X */ 
  1321. Xvoid    
  1322. Xre_fail(s, c)
  1323. Xchar *s;
  1324. Xchar c;
  1325. X{
  1326. X    fprintf(stderr, "%s [opcode %o]\n", s, c);
  1327. X    exit(1);
  1328. X}
  1329. SHAR_EOF
  1330. if test 292 -ne "`wc -c 're_fail.c'`"
  1331. then
  1332.     echo shar: error transmitting "'re_fail.c'" '(should have been 292 characters)'
  1333. fi
  1334. echo shar: extracting "'grep.c'" '(1014 characters)'
  1335. if test -f 'grep.c'
  1336. then
  1337.     echo shar: over-writing existing file "'grep.c'"
  1338. fi
  1339. sed 's/^X//' << \SHAR_EOF > 'grep.c'
  1340. X#ifdef vms
  1341. X#include stdio
  1342. X#else
  1343. X#include <stdio.h>
  1344. X#endif
  1345. X
  1346. X/*
  1347. X * Rudimentary grep to test regex routines.
  1348. X *
  1349. X * DEBUG is only applicable
  1350. X * to oZ version of regex. Make sure to 
  1351. X * compile regex.c with -DDEBUG as well.
  1352. X *
  1353. X */
  1354. Xextern char *re_comp();
  1355. Xextern re_exec();
  1356. X
  1357. Xmain(argc,argv)
  1358. Xchar *argv[];
  1359. X{
  1360. X    char str[512];
  1361. X    FILE *f;
  1362. X    register int n;
  1363. X    register char *p;
  1364. X
  1365. X    if (argc < 2)
  1366. X        error("usage: grep pat [file]");
  1367. X
  1368. X    if ((p = re_comp(argv[1])) != 0) {
  1369. X        printf("\t%s: %s\n", p, argv[1]);
  1370. X        exit(1);
  1371. X    }
  1372. X#ifdef DEBUG
  1373. X    symbolic(argv[1]);
  1374. X#endif
  1375. X    if (p = argv[2]) {
  1376. X        if ((f = fopen(p, "r")) == NULL) {
  1377. X            printf("cannot open %s\n", argv[2]);
  1378. X            exit(1);
  1379. X        }
  1380. X        while ((n = load(str, f)) != EOF)
  1381. X            if (re_exec(str))
  1382. X                printf("%s\n",str);
  1383. X
  1384. X    }
  1385. X    exit(0);
  1386. X}
  1387. Xload (s, f)
  1388. Xchar *s;
  1389. XFILE *f;
  1390. X{
  1391. X    register int c;
  1392. X    static int lineno = 0;
  1393. X
  1394. X    while ((c = getc(f)) != '\n' && c != EOF)
  1395. X        *s++ = c;
  1396. X    if (c == EOF)
  1397. X        return (EOF);
  1398. X    *s = (char) 0;
  1399. X    return (++lineno);
  1400. X}
  1401. X
  1402. Xerror(s) char *s ; 
  1403. X{ 
  1404. X    fprintf(stderr,"%s\n",s); 
  1405. X    exit(1); 
  1406. X}
  1407. SHAR_EOF
  1408. if test 1014 -ne "`wc -c 'grep.c'`"
  1409. then
  1410.     echo shar: error transmitting "'grep.c'" '(should have been 1014 characters)'
  1411. fi
  1412. echo shar: extracting "'makefile'" '(2472 characters)'
  1413. if test -f 'makefile'
  1414. then
  1415.     echo shar: over-writing existing file "'makefile'"
  1416. fi
  1417. sed 's/^X//' << \SHAR_EOF > 'makefile'
  1418. X#
  1419. X# regex routines (PUBLIC DOMAIN)
  1420. X#
  1421. X# by:    Ozan S. Yigit (oz)
  1422. X#    Dept. of Computer Science
  1423. X#    York University
  1424. X#
  1425. X# Applicable to BSD:
  1426. X#
  1427. X# If you have the generic(?) regex routines
  1428. X# than you can compare the timings of these
  1429. X# routines to the generic ones by:
  1430. X#
  1431. X#    make times
  1432. X#
  1433. X# which will create two rudimentary greps
  1434. X# lgrep and ogrep. lgrep will use the generic
  1435. X# regex routines, and ogrep will use oz version
  1436. X# of regex. Several patterns will be searched
  1437. X# in /usr/dict/words, and the output of the greps
  1438. X# will be compared. [for reasons of sanity]
  1439. X#
  1440. X# Surely, you will note, the time tests are somewhat
  1441. X# biased, since /usr/dict/words contain *short* lines,
  1442. X# thereby the real-life case of searching a complex
  1443. X# expression within a long line is not covered. You
  1444. X# will find, however, that the PD regex routines will
  1445. X# search *as fast* as the generic ones in most
  1446. X# cases, and about 10% slower in some cases, when
  1447. X# tested with files containing *long* lines. 
  1448. X# 
  1449. XCFLAGS = -O
  1450. X#
  1451. X# test patterns
  1452. X#
  1453. XPAT1 = '[d-f]zz*.*m'
  1454. XPAT2 = 'fo[ornt]*.*b[a-d]*'
  1455. XPAT3 = '.th.'
  1456. XPAT4 = '\(ab\)[a-d]*\1'
  1457. XPAT5 = 'burp'
  1458. X
  1459. XFILE = /usr/dict/words
  1460. XOUTD = /tmp/
  1461. X
  1462. XRSRC = regex.o re_fail.o
  1463. X
  1464. Xregex:  $(RSRC)
  1465. X#
  1466. X#    insert code to put these into a library
  1467. X#
  1468. Xrlint:
  1469. X    lint -phc regex.c
  1470. Xdebug:
  1471. X    cc -O -DDEBUG -o ogrep grep.c regex.c re_fail.c
  1472. X
  1473. Xlgrep:  grep.o
  1474. X    cc -o lgrep grep.o
  1475. X
  1476. Xogrep:  grep.o $(RSRC)
  1477. X    cc -o ogrep grep.o $(RSRC)
  1478. X
  1479. Xtimes:  lgrep ogrep
  1480. X    @echo generic regex vs oz regex
  1481. X#    @echo pattern: $(PAT1)
  1482. X    time ogrep $(PAT1) $(FILE) >$(OUTD)ogrep.out
  1483. X    time lgrep $(PAT1) $(FILE) >$(OUTD)lgrep.out
  1484. X    @echo output differences:
  1485. X    -diff $(OUTD)ogrep.out $(OUTD)lgrep.out
  1486. X    @echo "---"
  1487. X#    @echo pattern: $(PAT2)
  1488. X    time ogrep $(PAT2) $(FILE) >$(OUTD)ogrep.out
  1489. X    time lgrep $(PAT2) $(FILE) >$(OUTD)lgrep.out
  1490. X    @echo output differences:
  1491. X    -diff $(OUTD)ogrep.out $(OUTD)lgrep.out
  1492. X    @echo "---"
  1493. X#    echo pattern: $(PAT3)
  1494. X    time ogrep $(PAT3) $(FILE) >$(OUTD)ogrep.out
  1495. X    time lgrep $(PAT3) $(FILE) >$(OUTD)lgrep.out
  1496. X    @echo output differences:
  1497. X    -diff $(OUTD)ogrep.out $(OUTD)lgrep.out
  1498. X    @echo "---"
  1499. X#    echo pattern: $(PAT4)
  1500. X    time ogrep $(PAT4) $(FILE) >$(OUTD)ogrep.out
  1501. X    time lgrep $(PAT4) $(FILE) >$(OUTD)lgrep.out
  1502. X    @echo output differences:
  1503. X    -diff $(OUTD)ogrep.out $(OUTD)lgrep.out
  1504. X    @echo "---"
  1505. X#    echo pattern: $(PAT5)
  1506. X    time ogrep $(PAT5) $(FILE) >$(OUTD)ogrep.out
  1507. X    time lgrep $(PAT5) $(FILE) >$(OUTD)lgrep.out
  1508. X    @echo output differences:
  1509. X    -diff $(OUTD)ogrep.out $(OUTD)lgrep.out
  1510. X    @echo "---"
  1511. X    @rm $(OUTD)ogrep.out $(OUTD)lgrep.out
  1512. SHAR_EOF
  1513. if test 2472 -ne "`wc -c 'makefile'`"
  1514. then
  1515.     echo shar: error transmitting "'makefile'" '(should have been 2472 characters)'
  1516. fi
  1517. #    End of shell archive
  1518. exit 0
  1519.  
  1520.  
  1521.